package com.ddxcloud.movie.service.impl;

import cn.hutool.core.util.RandomUtil;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson2.JSONObject;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.internal.util.AlipaySignature;
import com.alipay.api.request.AlipayTradePagePayRequest;
import com.alipay.api.response.AlipayTradePagePayResponse;
import com.ddxcloud.common.constants.PayMethodConstant;
import com.ddxcloud.common.constants.PayTypeConstant;
import com.ddxcloud.common.constants.ResultStatusConstant;
import com.ddxcloud.common.constants.enums.PayStatusEnum;
import com.ddxcloud.common.utils.IpUtil;
import com.ddxcloud.common.utils.PayOrderUtil;
import com.ddxcloud.movie.config.alipay.AlipayConfig;
import com.ddxcloud.movie.config.properties.CommonProperties;
import com.ddxcloud.movie.dto.PayDTO;
import com.ddxcloud.movie.entity.PaymentOrder;
import com.ddxcloud.movie.service.AlipayService;
import com.ddxcloud.movie.service.PaymentOrderService;
import com.google.common.collect.Maps;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.nio.charset.StandardCharsets;
import java.util.Map;

@Service
@Slf4j
public class AlipayServiceImpl implements AlipayService {

    @Resource
    PaymentOrderService paymentOrderService;

    @Resource
    CommonProperties commonProperties;

    @Override
    public String pay(PayDTO dto, HttpServletRequest request, HttpServletResponse response) throws AlipayApiException {
        String outTradeNo = dto.getOrderId() + "_" + RandomUtil.randomNumbers(4);
        PaymentOrder paymentOrder = new PaymentOrder();
        paymentOrder.setOrderSn(PayOrderUtil.getOrderSn(PayTypeConstant.Payment));
        paymentOrder.setOrderId(dto.getOrderId());
        paymentOrder.setProductName("电影票");
        paymentOrder.setPayMethod(PayMethodConstant.ALIPAY);
        paymentOrder.setPayAmount(commonProperties.isDebug() ? 1 : dto.getAmount());
        paymentOrder.setPayStatus(PayStatusEnum.STATUS_0.getCode());
        paymentOrder.setCallbackUrl(commonProperties.getDomainName() + "/pay/alipay/notify");
        paymentOrder.setClientIp(IpUtil.getClientIp(request));
        paymentOrder.setOutTradeNo(outTradeNo);
        log.info("支付宝支付-请求参数 {}", JSONUtil.toJsonStr(paymentOrder));
        boolean res = paymentOrderService.save(paymentOrder);
        if (res) {
            // AlipayConfig.alipay_public_key = AlipaySignature.getAlipayPublicKey("appCertPublicKey_2021004133677064.crt");
            AlipayClient alipayClient = new DefaultAlipayClient(
                    AlipayConfig.gatewayUrl,
                    AlipayConfig.app_id,
                    AlipayConfig.merchant_private_key,
                    "json",
                    AlipayConfig.charset,
                    AlipayConfig.alipay_public_key,
                    AlipayConfig.sign_type);

            // 设置请求参数
            AlipayTradePagePayRequest alipayRequest = new AlipayTradePagePayRequest();
            alipayRequest.setReturnUrl(AlipayConfig.return_url);
            alipayRequest.setNotifyUrl(AlipayConfig.notify_url);

            // 付款金额（元），必填
            String total_amount = new BigDecimal(paymentOrder.getPayAmount()).divide(BigDecimal.valueOf(100), 2, RoundingMode.HALF_UP).toString();
            // 订单名称，必填
            String subject = paymentOrder.getProductName();
            // 商品描述，可空
            String body = paymentOrder.getProductName();
            JSONObject bizContent = new JSONObject();
            bizContent.put("out_trade_no", paymentOrder.getOrderSn());
            bizContent.put("total_amount", total_amount);
            bizContent.put("subject", subject);
            bizContent.put("body", body);
            bizContent.put("product_code", "FAST_INSTANT_TRADE_PAY");
            alipayRequest.setBizContent(bizContent.toString());
            try {
                AlipayTradePagePayResponse alipayTradePagePayResponse = alipayClient.pageExecute(alipayRequest);
                if(alipayTradePagePayResponse.isSuccess()) {
                    return alipayTradePagePayResponse.getBody();
                }
            } catch (AlipayApiException e) {
                log.error("支付宝支付-创建订单失败 {}", e.getErrMsg());
            }
        }
        return "";
    }

    @Override
    public String notify(HttpServletRequest request) {
        Map<String, String> params = Maps.newHashMap();
        try {
            Map<String, String[]> requestParams = request.getParameterMap();
            for (String o : requestParams.keySet()) {
                String[] values = requestParams.get(o);
                String valueStr = "";
                for (int i = 0; i < values.length; i++) {
                    valueStr = (i == values.length - 1) ? valueStr + values[i]
                            : valueStr + values[i] + ",";
                }
                // 乱码解决，这段代码在出现乱码时使用。
                valueStr = new String(valueStr.getBytes(StandardCharsets.ISO_8859_1), StandardCharsets.UTF_8);
                params.put(o, valueStr);
            }
            boolean flag = AlipaySignature.rsaCheckV1(params, AlipayConfig.alipay_public_key, AlipayConfig.charset, AlipayConfig.sign_type);
            if (flag) { // 验证成功
                log.info(params.toString());
                return ResultStatusConstant.SUCCESS;
            }
        } catch (Exception e) {
            log.info("alipayNotify errMsg: {}", e.getMessage());
            return ResultStatusConstant.FAIL;
        }
        return ResultStatusConstant.FAIL;
    }
}
